﻿using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine.Events;
using UnityEngine.EventSystems;

namespace ZXthex.CodingUI
{
    public class BaseCodingUI
    {

        protected static void SetDefaultRectTransform(RectTransform rT, float childSizeDelta = 0)
        {
            rT.localScale = Vector3.one;
            rT.localPosition = new Vector3();

            if (rT.GetComponent<ScrollRect>())
            {
                rT.sizeDelta = new Vector2(160, 150);
            }
            else
            {
                rT.sizeDelta = new Vector2(160, 30);
            }
            for (int i = 0; i < rT.childCount; i++)
            {
                var r = rT.GetChild(i) as RectTransform;

                r.localScale = Vector3.one;
                r.anchorMin = Vector2.zero;
                r.anchorMax = Vector2.one;
                r.sizeDelta = Vector2.one * childSizeDelta;
            }
        }

        protected static Text CreateTextGameObject()
        {
            var text = new GameObject("Text", typeof(RectTransform)).AddComponent<Text>();
            text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
            text.color = Color.black;

            return text;
        }


        static List<CodingTuple> detectedTransforms;

        static void InitTransformActionList()
        {
            detectedTransforms = new List<CodingTuple>();
            EventSystem.current.StartCoroutine(TransformChangeDetector());
        }

        static IEnumerator TransformChangeDetector()
        {
            while (true)
            {
                yield return null;
                for (int i = 0; i < detectedTransforms.Count; i++)
                {
                    if (detectedTransforms[i].ui.transform.hasChanged
                        || detectedTransforms[i].childCount != detectedTransforms[i].ui.transform.childCount)
                    {
                        var action = detectedTransforms[i].callback;
                        if (action != null)
                        {
                            action.Invoke(detectedTransforms[i].ui.transform.childCount - detectedTransforms[i].childCount);
                        }
                        detectedTransforms[i].ui.transform.hasChanged = false;
                        detectedTransforms[i].childCount = detectedTransforms[i].ui.transform.childCount;
                    }
                }
            }
        }


        protected delegate void TransformOrChildCountChangeCallback(int childCountChangedDelta);
        class CodingTuple
        {
            public UIBehaviour ui;
            public int childCount;
            public TransformOrChildCountChangeCallback callback;

            public override bool Equals(object obj)
            {
                if (ui == null)
                    return obj is CodingTuple 
                        && (obj as CodingTuple).ui == null;

                return obj is CodingTuple
                    && ui.Equals((obj as CodingTuple).ui);
            }

            public override int GetHashCode()
            {
                if (ui == null) return 0;
                return ui.GetHashCode();
            }
        }


        protected void RegisterOnTransformAndChildCountChanged(UIBehaviour ui, TransformOrChildCountChangeCallback callback)
        {
            if (detectedTransforms == null)
            {
                InitTransformActionList();
            }

            var tuple = new CodingTuple { ui = ui, childCount = ui.transform.childCount, callback = callback };

            var ind = detectedTransforms.IndexOf(tuple);
            if (ind < 0)
            {
                ui.transform.hasChanged = false;
                detectedTransforms.Add(tuple);
            }
            else
            {
                detectedTransforms[ind].callback = callback;
            }

        }

    }
}